import { CancelExecutor, CancelTokenSource, Canceler } from '../types'
// 注意，类又可以当值，也可以当类型
// 当类型的时候，他的值为实例化对象
// 当值的时候，类型应该为类类型
import Cancel from './Cancel'

interface ResolvePromise {
  (reason?: Cancel): void
}

export default class CancelToken {
  promise: Promise<Cancel>
  reason?: Cancel

  constructor(executor: CancelExecutor) {
    let resolvePromise: ResolvePromise

    this.promise = new Promise<Cancel>(resolve => {
      resolvePromise = resolve as ResolvePromise
    })

    // 测试普通函数的情况
    executor(message => {
      if (this.reason) {
        return
      }

      this.reason = new Cancel(message)
      resolvePromise(this.reason)
    })
  }

  throwIfRequested() {
    if (this.reason) {
      // 这里抛出的异常（只会被顶层捕获），也就是Axios的request方法返回的promise对象的catch捕捉
      throw this.reason
    }
  }

  static source(): CancelTokenSource {
    let cancel!: Canceler
    const token = new CancelToken(c => {
      cancel = c
    })

    return {
      cancel,
      token
    }
  }
}
